package com.ht.aems.eas;

import com.ht.aems.fesmodel.data.MeasurePoint;
import rtdb.pas.AvcFesPoints;

import java.util.Calendar;
import java.util.Date;

/**
 * Created by IntelliJ IDEA.
 * User: Dong Shufeng
 * Date: 11-9-7
 */
public class AvcPointsFiller {

    public static void updateAvcPoints(AvcFesPoints avcPoints, long endTime, long elapseTime, double pLossBefore, double pLossAfter, boolean converged) {
        if (avcPoints.dayCount == null) ;
        else if (setMeasureTime(endTime, avcPoints.dayCount))
            avcPoints.dayCount.setEngValue(1);
        else
            avcPoints.dayCount.setEngValue(avcPoints.dayCount.getEngValue() + 1);

        if (avcPoints.monthCount == null) ;
        else if (setMeasureTime(endTime, avcPoints.monthCount))
            avcPoints.monthCount.setEngValue(1);
        else
            avcPoints.monthCount.setEngValue(avcPoints.monthCount.getEngValue() + 1);

        if (avcPoints.yearCount == null) ;
        else if (setMeasureTime(endTime, avcPoints.yearCount))
            avcPoints.yearCount.setEngValue(1);
        else
            avcPoints.yearCount.setEngValue(avcPoints.yearCount.getEngValue() + 1);

        if (avcPoints.dayConvergeRate == null || avcPoints.dayCount == null) ;
        else if (setMeasureTime(endTime, avcPoints.dayConvergeRate))
            avcPoints.dayConvergeRate.setEngValue(converged ? 1.0 : 0.0);
        else
            avcPoints.dayConvergeRate.setEngValue(((converged ? 1.0 : 0.0) + avcPoints.dayConvergeRate.getEngValue() * avcPoints.dayCount.getEngValue()) / (1.0 + avcPoints.dayCount.getEngValue()));

        if (avcPoints.monthConvergeRate == null || avcPoints.monthCount == null) ;
        else if (setMeasureTime(endTime, avcPoints.monthConvergeRate))
            avcPoints.monthConvergeRate.setEngValue(converged ? 1.0 : 0.0);
        else
            avcPoints.monthConvergeRate.setEngValue(((converged ? 1.0 : 0.0) + avcPoints.monthConvergeRate.getEngValue() * avcPoints.monthCount.getEngValue()) / (1.0 + avcPoints.monthCount.getEngValue()));

        if (avcPoints.yearConvergeRate == null || avcPoints.yearCount == null) ;
        else if (setMeasureTime(endTime, avcPoints.yearConvergeRate))
            avcPoints.yearConvergeRate.setEngValue(converged ? 1.0 : 0.0);
        else
            avcPoints.yearConvergeRate.setEngValue(((converged ? 1.0 : 0.0) + avcPoints.yearConvergeRate.getEngValue() * avcPoints.yearCount.getEngValue()) / (1.0 + avcPoints.yearCount.getEngValue()));

        if (avcPoints.dayAvailableRate != null && avcPoints.dayConvergeRate != null) {
            avcPoints.dayAvailableRate.setTimestamp(new Date(endTime));
            avcPoints.dayAvailableRate.setEngValue(avcPoints.dayConvergeRate.getEngValue());
        }
        if (avcPoints.monthAvailableRate != null && avcPoints.monthConvergeRate != null) {
            avcPoints.monthAvailableRate.setTimestamp(new Date(endTime));
            avcPoints.monthAvailableRate.setEngValue(avcPoints.monthConvergeRate.getEngValue());
        }
        if (avcPoints.yearAvailableRate != null && avcPoints.yearConvergeRate != null) {
            avcPoints.yearAvailableRate.setTimestamp(new Date(endTime));
            avcPoints.yearAvailableRate.setEngValue(avcPoints.yearConvergeRate.getEngValue());
        }
        //current
        if (avcPoints.elapsedTime != null) {
            avcPoints.elapsedTime.setTimestamp(new Date(endTime));
            avcPoints.elapsedTime.setEngValue(elapseTime);
        }
        if (!converged)
            return;
        if (avcPoints.pLossBefore != null)
            avcPoints.pLossBefore.setEngValue(pLossBefore);
        if (avcPoints.pLossAfter != null)
            avcPoints.pLossAfter.setEngValue(pLossAfter);
    }

    /**
     * @param seTime end time state estimation
     * @param p      the measurement point to be set
     * @return if the value of the measurement should be reset
     */
    private static boolean setMeasureTime(long seTime, MeasurePoint p) {
        if (p.getTimestamp() == null) {
            p.setTimestamp(new Date(seTime));
            return true;
        }
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(seTime);
        Calendar pointTime = Calendar.getInstance();
        pointTime.setTime(p.getTimestamp());
        int rtType = p.getMeasureType();
        boolean result = false;
        switch (rtType) {
            case MeasurePoint.DAY:
                if (pointTime.get(Calendar.YEAR) != c.get(Calendar.YEAR) ||
                        pointTime.get(Calendar.DAY_OF_YEAR) != c.get(Calendar.DAY_OF_YEAR))
                    result = true;
            case MeasurePoint.MONTH:
                if (pointTime.get(Calendar.YEAR) != c.get(Calendar.YEAR) ||
                        pointTime.get(Calendar.MONTH) != c.get(Calendar.MONTH))
                    result = true;
            case MeasurePoint.YEAR:
                if (pointTime.get(Calendar.YEAR) != c.get(Calendar.YEAR))
                    result = true;
            default:
                break;
        }
        p.setTimestamp(new Date(seTime));
        return result;
    }
}
